// progtest.cc 
//	Test routines for demonstrating that Nachos can load
//	a user program and execute it.  
//
//	Also, routines for testing the Console hardware device.
//
// Copyright (c) 1992-1993 The Regents of the University of California.
// All rights reserved.  See copyright.h for copyright notice and limitation 
// of liability and disclaimer of warranty provisions.

#include "copyright.h"
#include "system.h"
#include "console.h"
#include "addrspace.h"
#include "synch.h"
#include "string.h"
//#include "noff.h"
#include "syscall.h"
//#include "exception.cc"
#define QUANTUM 100

//----------------------------------------------------------------------
// StartProcess
// 	Run a user program.  Open the executable, load it into
//	memory, and jump to it.
//----------------------------------------------------------------------
void
StartProcess(char *filename)
{

  //OpenFile *executable = fileSystem->Open(filename);
  //NoffHeader noffH;
  //unsigned int i, size;

   //executable->ReadAt((char *)&noffH, sizeof(noffH), 0);
   //machine->WriteRegister(4,noffH.code.virtualAddr);
   //machine->WriteRegister(5,noffH.code.size);
   //system->copyout(noffH.code.virtualAddr,noffH.code.size, noffH.code);
   //Exec_Syscall(noffH.code.virtualAddr,noffH.code.size);
    OpenFile *executable = fileSystem->Open(filename);
    AddrSpace *space;

    if (executable == NULL) {
	printf("Unable to open file %s\n", filename);
	return;
    }
    else printf("StartProcess: FILE %s OPENED\n", filename);
   
   

    space = new AddrSpace(executable);
    currentThread->space = space;
    
    //must be after new AddrSpace() or else the addrspace will think this main thread is actually a new thread
    processTable->setMainThread(currentThread);

    Process *newprocess = new Process(space);
    processTable->addProcess(newprocess);
    newprocess->addThread(currentThread);
#ifdef NETWORK
    newprocess->setMailBox(1);
#endif




    //    delete executable;			// close file

    space->InitRegisters();		// set the initial register values
    space->RestoreState();		// load page table register

    machine->Run();			// jump to the user progam
    ASSERT(FALSE);		
                                         //machine->Run never returns;
                                         //the address space exits
					// by doing the syscall "exit"
}

// Data structures needed for the console test.  Threads making
// I/O requests wait on a Semaphore to delay until the I/O completes.

static Console *console;
static Semaphore *readAvail;
static Semaphore *writeDone;

//----------------------------------------------------------------------
// ConsoleInterruptHandlers
// 	Wake up the thread that requested the I/O.
//----------------------------------------------------------------------

static void ReadAvail(int arg) { readAvail->V(); }
static void WriteDone(int arg) { writeDone->V(); }

//----------------------------------------------------------------------
// ConsoleTest
// 	Test the console by echoing characters typed at the input onto
//	the output.  Stop when the user types a 'q'.
//----------------------------------------------------------------------

void 
ConsoleTest (char *in, char *out)
{
    char ch;

    console = new Console(in, out, ReadAvail, WriteDone, 0);
    readAvail = new Semaphore("read avail", 0);
    writeDone = new Semaphore("write done", 0);
    
    for (;;) {
	readAvail->P();		// wait for character to arrive
	ch = console->GetChar();
	console->PutChar(ch);	// echo it!
	writeDone->P() ;        // wait for write to finish
	if (ch == 'q') return;  // if q, quit
    }
}

